import time
import random

# Deepseek对于速率限制的说明：https://api-docs.deepseek.com/zh-cn/quick_start/rate_limit，https://api-docs.deepseek.com/zh-cn/quick_start/error_codes
# 硅基流动对于速率限制的说明：https://docs.siliconflow.cn/cn/userguide/rate-limits/rate-limit-and-upgradation


# ========== 自定义异常类 ==========
class RateLimitError(Exception):
    """限流异常类"""

    def __init__(self, message="请求频率超过限制"):
        self.status_code = 429
        self.message = message
        super().__init__(self.status_code, self.message)


# ========== 全局状态变量 ==========
# 熔断器配置参数
FAILURE_THRESHOLD = 3  # 熔断失败阈值: 连续失败次数达到此值触发熔断
RECOVERY_TIMEOUT = 5  # 恢复等待时间(秒): 熔断后等待恢复的时间

# 熔断器运行时状态
failure_count = 0  # 失败计数: 记录连续失败次数
last_failure_time = 0  # 上次失败时间: 记录最后一次失败的时间戳
circuit_state = "CLOSED"  # 熔断状态: CLOSED(关闭)/OPEN(打开)/HALF_OPEN(半开)


# ========== 模拟API接口 ==========
def mock_api_call():
    """模拟API调用：20%概率抛出429异常"""
    if random.random() < 0.2:  # 20%概率触发限流，模拟实际API限流的返回情况
        raise RateLimitError()  # 抛出限流异常
    return {"status": "success"}  # 正常返回


# ========== 熔断机制核心函数 ==========
def check_circuit_breaker():
    """
    检查熔断状态
    返回值:
        True: 允许请求通过
        False: 拒绝请求(熔断中)
    """
    global circuit_state, last_failure_time

    if circuit_state == "OPEN":
        # 检查是否已过恢复等待时间
        if (time.time() - last_failure_time) > RECOVERY_TIMEOUT:
            # 进入半开状态: 允许少量请求尝试恢复
            circuit_state = "HALF_OPEN"
            return True
        else:
            # 仍在熔断冷却期内
            print(
                f"[熔断保护] 请{int(RECOVERY_TIMEOUT - (time.time()-last_failure_time))}秒后重试"
            )
            return False
    return True  # 熔断器关闭或半开状态时允许请求


def record_failure(exception):
    """记录失败并触发熔断"""
    global failure_count, last_failure_time, circuit_state

    failure_count += 1
    last_failure_time = time.time()

    if failure_count >= FAILURE_THRESHOLD:
        circuit_state = "OPEN"
        print(f"[熔断触发] 服务已熔断，进入冷却期，持续{RECOVERY_TIMEOUT}秒")
        for i in range(RECOVERY_TIMEOUT, 0, -1):
            print(f"[冷却中] 请{int(i)}秒后重试...")
            time.sleep(1)


def reset_circuit():
    """重置状态"""
    global failure_count, circuit_state
    failure_count = 0
    circuit_state = "CLOSED"


# ========== 主调用函数 ==========
def safe_api_call():
    """带熔断保护的API调用"""
    if not check_circuit_breaker():
        return None

    try:
        # 模拟API调用，实际使用时替换为实际API调用
        response = mock_api_call()
        reset_circuit()
        return response

    except RateLimitError as e:
        print(f"[限流警告] 状态码{e.status_code}: {e.message}")
        record_failure(e)
        return None

    except Exception as e:
        print(f"[未知错误] {str(e)}")
        record_failure(e)
        return None


# ========== 测试运行 ==========
if __name__ == "__main__":
    attempt = 1
    while True:
        print(f"\n--- 尝试调用 #{attempt} ---")
        result = safe_api_call()

        if result:
            print("✅ 调用成功")
        else:
            print(f"❌ 当前熔断状态: {circuit_state} | 连续失败: {failure_count}")

        attempt += 1
        if attempt > 70:
            break
        time.sleep(1)  # 控制测试节奏

    print("\n测试结束")
